/*
 * Copyright NEC Europe Ltd. 2006-2007
 * 
 * This file is part of the context simulator called Siafu.
 * 
 * Siafu is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * Siafu is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package it.polimi.hospital;

import static it.polimi.hospital.Constants.DEFAULT_SPEED;
import static it.polimi.hospital.Constants.Fields.ACTIVITY;
import static it.polimi.hospital.Constants.Fields.TYPE;

import it.polimi.hospital.Constants.Activity;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;

import de.nec.nle.siafu.behaviormodels.BaseWorldModel;
import de.nec.nle.siafu.exceptions.NothingNearException;
import de.nec.nle.siafu.exceptions.PlaceTypeUndefinedException;
import de.nec.nle.siafu.graphics.markers.BalloonMarker;
import de.nec.nle.siafu.model.Agent;
import de.nec.nle.siafu.model.Place;
import de.nec.nle.siafu.model.Position;
import de.nec.nle.siafu.model.Trackable;
import de.nec.nle.siafu.model.World;
import de.nec.nle.siafu.types.BooleanType;
import de.nec.nle.siafu.types.EasyTime;
import de.nec.nle.siafu.types.Text;

/**
 * The world model for the simulation. In this case, the conference room calls
 * for a global meeting which some staff members attend.
 * 
 * @author Miquel Martin
 */
public class WorldModel extends BaseWorldModel {


	private Place leftEntrance;
	private Place rightEntrance;
	private Place block;
	
	private ArrayList<Place> screens = new ArrayList<Place>();

	private ArrayList<Place> lab = new ArrayList<Place>();
	private ArrayList<Place> radiology = new ArrayList<Place>();
	private ArrayList<Place> physiotherapy = new ArrayList<Place>();
	
	private ArrayList<Place> redArrows = new ArrayList<Place>();
	private ArrayList<Place> greenArrows = new ArrayList<Place>();
	private ArrayList<Place> blueArrows = new ArrayList<Place>();
	private ArrayList<Place> yellowArrows = new ArrayList<Place>();
		
	private ArrayList<Agent> redIndicators = new ArrayList<Agent>();
	private ArrayList<Agent> greenIndicators = new ArrayList<Agent>();
	private ArrayList<Agent> blueIndicators = new ArrayList<Agent>();
	private ArrayList<Agent> yellowIndicators = new ArrayList<Agent>();
	
	private Agent blockAgent;
	
	private RoutingManager manager = null;
	
	public RoutingManager getManager() {
		return this.manager;
	}
	
	public void setBlockAgent(Agent a) {
		this.blockAgent = a;
	}
	
	public Agent getBlockAgent() {
		return this.blockAgent;
	}
	
	public void addRedArrow(Place p) {
		redArrows.add(p);
	}
	public void addBlueArrow(Place p) {
		blueArrows.add(p);
	}
	public void addGreenArrow(Place p) {
		greenArrows.add(p);
	}
	public void addYellowArrow(Place p) {
		yellowArrows.add(p);
	}
	
	public void addLab(Place p) {
		lab.add(p);
	}
	public void addRadiology(Place p) {
		radiology.add(p);
	}
	public void addPhysiotherapy(Place p) {
		physiotherapy.add(p);
	}
	
	public void addRedIndicator(Agent a) {
		redIndicators.add(a);
	}
	public void addGreenIndicator(Agent a) {
		greenIndicators.add(a);
	}
	public void addBlueIndicator(Agent a) {
		blueIndicators.add(a);
	}
	public void addYellowIndicator(Agent a) {
		yellowIndicators.add(a);
	}
	public void addScreen(Place p) {
		screens.add(p);
	}
	
	public Place getLeftEntrance() {
		return leftEntrance;
	}
	public Place getRightEntrance() {
		return rightEntrance;
	}
	public Place getBlock(){
		return block;
	}
	public Place getLab(int num) {
		return lab.get(num);
	}
	public Place getRadiology(int num) {
		return radiology.get(num);
	}
	public Place getPhysiotherapy(int num) {
		return physiotherapy.get(num);
	}
	public Place getScreen(int num) {
		return screens.get(num);
	}
	public Place getRedArrow(int num) {
		return redArrows.get(num);
	}
	public Place getGreenArrow(int num) {
		return greenArrows.get(num);
	}
	public Place getYellowArrow(int num) {
		return yellowArrows.get(num);
	}
	public Place getBlueArrow(int num) {
		return blueArrows.get(num);
	}

	
	
	
	/**
	 * Create the world model.
	 * 
	 * @param world the simulation's world.
	 */
	public WorldModel(final World world) {
		super(world);
	}

	/**
	 * Add the Busy variable to the info field of all the places.
	 * 
	 * @param places the places created so far by the images
	 */
	@Override
	public void createPlaces(final ArrayList<Place> places) {
		
		Iterator<Place> itDoors = null;
		Iterator<Place> itScreens = null;
		Iterator<Place> itLabs = null;
		Iterator<Place> itRadiology = null;
		Iterator<Place> itPhysiotherapy = null;
		Iterator<Place> itRedArrows = null;
		Iterator<Place> itGreenArrows = null;
		Iterator<Place> itBlueArrows = null;
		Iterator<Place> itYellowArrows = null;
		Iterator<Place> itBlock = null;
		
		try {
			itDoors = world.getPlacesOfType("Door").iterator();		
			itScreens = world.getPlacesOfType("Screen").iterator();
			itLabs = world.getPlacesOfType("Lab").iterator();
			itRadiology = world.getPlacesOfType("Radiology").iterator();
			itPhysiotherapy = world.getPlacesOfType("Physiotherapy").iterator();
			itRedArrows = world.getPlacesOfType("RedArrow").iterator();
			itGreenArrows = world.getPlacesOfType("GreenArrow").iterator();
			itBlueArrows = world.getPlacesOfType("BlueArrow").iterator();
			itYellowArrows = world.getPlacesOfType("YellowArrow").iterator();
			itBlock = world.getPlacesOfType("Block").iterator();	
		} catch (PlaceTypeUndefinedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		leftEntrance = itDoors.next();
		rightEntrance = itDoors.next();
		block = itBlock.next();
		
		while (itScreens.hasNext()) {
			addScreen(itScreens.next());
		}
		
		
		while (itLabs.hasNext()){
			addLab(itLabs.next());
		}
		while (itRadiology.hasNext()) {
			addRadiology(itRadiology.next());
		}
		while (itPhysiotherapy.hasNext()) {
			addPhysiotherapy(itPhysiotherapy.next());
		}
		
		while (itRedArrows.hasNext()){
			addRedArrow(itRedArrows.next());
		}
		while (itBlueArrows.hasNext()) {
			addBlueArrow(itBlueArrows.next());
		}
		while (itGreenArrows.hasNext()) {
			addGreenArrow(itGreenArrows.next());
		}
		while (itYellowArrows.hasNext()) {
			addYellowArrow(itYellowArrows.next());
		}
		
		manager = new RoutingManager(this);
		
	
	}

	/**
	 * Schedule a daily meeting, and ensure all the necessary Agents are
	 * invited over to it when the time comes.
	 * 
	 * @param places the places in the simulation.
	 */
	public void doIteration(final Collection<Place> places) {
		
//		Calendar time = world.getTime();
//		EasyTime now =	new EasyTime(time.get(Calendar.HOUR_OF_DAY), time.get(Calendar.MINUTE));
//		if(now.getHour()==9)
//			manager.setConfiguration(1);
//		else
//			manager.setConfiguration(0);
		
		ArrayList<Trackable> agents = null;
		ArrayList<Agent> redAgent = null;
		ArrayList<Agent> blueAgent = null;
		ArrayList<Agent> greenAgent = null;
		ArrayList<Agent> yellowAgent = null;
		
		for(int index=0; index<6; index++){
		try {
			
			redAgent = new ArrayList<Agent>();
			blueAgent = new ArrayList<Agent>();
			greenAgent = new ArrayList<Agent>();
			yellowAgent = new ArrayList<Agent>();
			agents = world.findAllAgentsNear(screens.get(index).getPos(), 80, false);
			
			for(int i=0; i<agents.size(); i++){
				Agent ag = (Agent) agents.get(i);
				if(((Text)ag.get(TYPE)).getText().equalsIgnoreCase("Magenta"))
					redAgent.add(ag);
				else if(((Text)ag.get(TYPE)).getText().equalsIgnoreCase("Blue"))
					blueAgent.add(ag);
				else if(((Text)ag.get(TYPE)).getText().equalsIgnoreCase("Green"))
					greenAgent.add(ag);
				else if(((Text)ag.get(TYPE)).getText().equalsIgnoreCase("Yellow"))
					yellowAgent.add(ag);
			}
			
			//case red
			if(redAgent.size()>0){
				//setDestination
				for(int i=0; i<redAgent.size(); i++){
					redAgent.get(i).setDestination(manager.getNextDestination(index, "red"));
				}
				redIndicators.get(index).setDir(manager.getIndicatorDirection(index, "red"));
			}else{
				redIndicators.get(index).setDir(1);
			}
			
			//case blue
			if(blueAgent.size()>0){
				//setDestination
				for(int i=0; i<blueAgent.size(); i++){
					blueAgent.get(i).setDestination(manager.getNextDestination(index, "blue"));
				}
				blueIndicators.get(index).setDir(manager.getIndicatorDirection(index, "blue"));
			}else{
				blueIndicators.get(index).setDir(1);
			}
			
			//case green
			if(greenAgent.size()>0){
				//setDestination
				for(int i=0; i<greenAgent.size(); i++){
					greenAgent.get(i).setDestination(manager.getNextDestination(index, "green"));
				}
				greenIndicators.get(index).setDir(manager.getIndicatorDirection(index, "green"));
			}else{
				greenIndicators.get(index).setDir(1);
			}
			
			//case yellow
			if(yellowAgent.size()>0){
				//setDestination
				for(int i=0; i<yellowAgent.size(); i++){
					yellowAgent.get(i).setDestination(manager.getNextDestination(index, "yellow"));
				}
				yellowIndicators.get(index).setDir(manager.getIndicatorDirection(index, "yellow"));
			}else{
				yellowIndicators.get(index).setDir(1);
			}
			
		} catch (NothingNearException e) {
			// TODO Auto-generated catch block
			//e.printStackTrace();
		}
		
		}
		
		//Caso Screen 4...
		
		

	}

}
